﻿#include <iostream>
#include <fstream>
#include <thread>

#include <zmq.hpp>

#include "../../inc/helper.hpp"
#include "nlohmann/json.hpp"

using nlohmann::json;

struct DcConfig
{
	int m_state_port;
};

std::string read_file(std::string file_name)
{
	std::ifstream file;
	file.open(file_name, std::ios_base::in | std::ios_base::out);
	if (!file)
	{
		info("failed to open file {}", file_name);
		return "";
	}

	file.seekg(0, std::ios_base::end);
	size_t file_size = static_cast<size_t>(file.tellg());
	file.seekg(0, std::ios_base::beg);

	std::string content;
	content.resize(file_size);
	if (file_size <= 0)
	{
		info("empty file: {}", file_name);
		return "";
	}

	file.read(&content[0], file_size);
	return content;
}

DcConfig parse_config(std::string content)
{
	auto json_obj = json::parse(content);
	DcConfig cfg;
	cfg.m_state_port = json_obj["state_port"].get<int>();
	return cfg;
}

DcConfig get_dc_config(std::string dc_name)
{
	std::string cfg_file = dc_name + ".json";
	std::string content = read_file(cfg_file);
	return parse_config(content);
}

int main(int argc, char* argv[])
{
	if (argc < 2)
	{
		info("syntax: peering1 me {you}...");
		return 1;
	}

	std::string self = argv[1];
	DcConfig my_cfg = get_dc_config(self);
	info("preparing broker at {}-{}...", self, my_cfg.m_state_port);
	

	zmq::context_t ctx;
	zmq::socket_t statebe(ctx, zmq::socket_type::pub);
	statebe.bind(fmt::format("tcp://*:{}", my_cfg.m_state_port));

	zmq::socket_t statefe(ctx, zmq::socket_type::sub);
	statefe.setsockopt(ZMQ_SUBSCRIBE, "", 0);
	for (int i = 2; i < argc; ++i)
	{
		DcConfig dc_config = get_dc_config(argv[i]);
		info("connecting to state backend at {}-{}", argv[i], dc_config.m_state_port);
		statefe.connect(fmt::format("tcp://localhost:{}", dc_config.m_state_port));
	}

	std::vector<zmq::pollitem_t> items = {
		{ statefe, 0, ZMQ_POLLIN, 0 }
	};
	while (true)
	{
		zmq::poll(items, 1000);
		if (items[0].revents & ZMQ_POLLIN)
		{
			auto msgs = zmsg_recv(statefe);
			std::string peer_name = to_string(msgs[0]);
			std::string available = to_string(msgs[1]);
			info("{} - {} workers free", peer_name, available);
		}
		else
		{
			std::deque<zmq::message_t> msgs;
			msgs.emplace_back(to_message(self));
			msgs.emplace_back(to_message(fmt::format("{}", rand()%10)));
			zmsg_send(statebe, msgs);
		}
	}
}